package cn.iocoder.yudao.module.engine.monitor;

import io.netty.util.internal.PlatformDependent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.BufferPoolMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class DirectMemoryMonitor {
    private static final Logger log = LoggerFactory.getLogger(DirectMemoryMonitor.class);
    private static final long CHECK_INTERVAL = 60; // seconds

    public static void start() {
        Executors.newSingleThreadScheduledExecutor()
                .scheduleAtFixedRate(() -> {
                    try {
                        doCheck();
                    } catch (Exception e) {
                        log.error("Direct memory check failed", e);
                    }
                }, 0, CHECK_INTERVAL, TimeUnit.SECONDS);
    }

    private static void doCheck() {
        try {
            // 方案1：优先使用Netty指标
            if (PlatformDependent.hasDirectBufferNoCleanerConstructor()) {
                long used = PlatformDependent.usedDirectMemory();
                long max = PlatformDependent.maxDirectMemory();
                logMemoryStatus(used, max);
                return;
            }

            // 方案2：使用标准JMX
            List<BufferPoolMXBean> pools = ManagementFactory
                    .getPlatformMXBeans(BufferPoolMXBean.class);

            for (BufferPoolMXBean pool : pools) {
                if ("direct".equals(pool.getName())) {
                    logMemoryStatus(
                            pool.getMemoryUsed(),
                            pool.getTotalCapacity()
                    );
                    return;
                }
            }

            log.warn("No direct buffer pool found");
        } catch (Exception e) {
            log.error("Memory check error", e);
        }
    }

    private static void logMemoryStatus(long usedBytes, long maxBytes) {
        long usedMB = usedBytes / 1024 / 1024;
        long maxMB = maxBytes / 1024 / 1024;
        int percent = maxMB == 0 ? 0 : (int) (usedMB * 100 / maxMB);

        log.info("Direct memory: {}MB/{}MB ({}%)", usedMB, maxMB, percent);

        if (percent > 90) {
            //log.warn("⚠️ Direct memory over 90% usage!");
            // 触发预警或保护措施
        }
    }
}